/*
 * historia.h
 *
 * Copyright (C) 2008, 2009
 *
 * Lukasz Bieniasz-Krzywiec
 * Dariusz Leniowski
 */

#ifndef HISTORIA_H_
#define HISTORIA_H_

#include "../config.h"

/*
 * historia<T,N> obiekt przechowywujacy historie dlugosci N obiektow typu T
 * Zalozenia:
 * - N > 0
 * - zero da sie skonwertowac do T
 * - T jest zamkniete na dodawanie i dzielenie przez inta
 * - przesumowanie wszystkich trzymanych T jest poprawnym T (np. nie przepelni sie)
 * Wynik:
 * - obiekt przechowywujacy maksymalnie N probek
 * - starsze probki sa usredniane
 */

template <class T>
class historia {
  T   *dane;
  T   suma;
  int SIZE;
  int _size;

public:
  virtual ~historia();

  historia(int);

  /* Zwraca liczbe przechowywanych probek */
  int size();

  /* Dodaje nowa probke */
  const T operator=(const T x);

  /* Dodaje wartosc do ostatniej probki */
  const T operator+=(const T x);

  /*
   * Zwraca ostatnia probke
   * Zalozenia:
   * - w historii mamy przynajmiej jedna probke
   */
  operator const T () const;

  /*
   * Zwraca n-ostatnia probke
   * Argumenty:
   * - n -- ktora probke zwrocic
   * Zalozenia:
   * - w historii mamy przynajmiej jedna probke
   * Wynik:
   * - jezeli n < ilosc probek trzymanych explicite w historii,
   *   to zwraca n-ostatnia probke (0 znaczy ostatnia)
   * - jezeli n > ilosc probek trzymanych explicite w historii,
   *   to zwraca srednia wszystkich probek.
   */
  const T operator[] (const int n) const;
};

template <class T>
historia<T>::~historia() {}

template <class T>
historia<T>::historia(int n) : suma(0), SIZE(n), _size(0) { dane = new T[n]; }

template <class T>
int historia<T>::size() { return _size; }

template <class T>
const T historia<T>::operator=(const T x) {
  suma += x;
  dane[(_size++) % SIZE] = x;
  return x;
}
template <class T>
const T historia<T>::operator+=(const T x) {
	suma += x;
	dane[(_size+SIZE-1) % SIZE] += x;
	return dane[(_size+SIZE-1) % SIZE];
}

template <class T>
historia<T>::operator const T () const { 
  ASSERT(_size > 0);
  return dane[(_size-1+SIZE)%SIZE]; 
}

template <class T>
const T historia<T>::operator[] (const int n) const
{
  ASSERT(n >= 0);
  ASSERT(_size > 0);
  if(n >= SIZE || n >= _size) return (suma/_size);
  else return dane[(_size-1+SIZE-n)%SIZE];
}

#endif /* HISTORIA_H_ */

